#!/bin/sh
# for bububox's ash
#minibackup.sh

MNT_DIR='/mnt/'
BACKTITLE='MiniBackup-linux'
NOT_SUPPORT_STR="Not_Support"
LOG_FILE="/tmp/minibackup.log"
DIALOG_HEIGH=25
DIALOG_WIDTH=80
NO_SHADOW=""

HANDLE_TYPE=""
OPERATION_TYPE=""
SOUR_PARTITION=""
DEST_PARTITION=""
IMAGE_DICTIONARY=""
TOOL_TYPE="partclone-gzip"
EXIT_TYPE=""
SOUR_DISK=""

init_parameters() {
dialog --print-maxsize 2> /tmp/minibackup_size_para 
local max_heigh=`cat  /tmp/minibackup_size_para | tr -d ',' | awk '{ print $2}' `
local max_width=`cat  /tmp/minibackup_size_para | tr -d ',' | awk '{ print $3}' `
if [ $max_heigh -gt 30 ]; then  max_heigh=`expr $max_heigh - 6 `;else max_heigh=`expr $max_heigh - 4`;NO_SHADOW="--no-shadow"; fi
if [ $max_width -gt 100  ]; then max_width=`expr $max_width - 20 `; fi
DIALOG_HEIGH=$max_heigh
DIALOG_WIDTH=$max_width

cmdline=`cat /proc/cmdline`
#cmdline="type=save sour_partition=sda5 image_partition=sda10 image_dictionary=sda5 exit=reboot"
cmd_para=`echo $cmdline | grep "type=" -o`
if [ ${#cmd_para} -gt 0 ]; then
	handle_type=${cmdline#*type=}
	handle_type=${handle_type%% *}
	HANDLE_TYPE="auto"
	if [ "$handle_type" = "save" ]; then
		OPERATION_TYPE="Save"
	elif [ "$handle_type" = "restore" ]; then
		OPERATION_TYPE="Restore"
	else
		HANDLE_TYPE=""
	fi

	if [ "$HANDLE_TYPE" = "auto" ]; then
		cmd_para=`echo $cmdline | grep "sour_partition=" -o`
		if [ ${#cmd_para} -gt 0 ]; then
			SOUR_PARTITION=${cmdline#*sour_partition=}
			SOUR_PARTITION=${SOUR_PARTITION%% *}
		fi
		cmd_para=`echo $cmdline | grep "image_partition=" -o`
		if [ ${#cmd_para} -gt 0 ]; then
			DEST_PARTITION=${cmdline#*image_partition=}
			DEST_PARTITION=${DEST_PARTITION%% *}
		fi
		cmd_para=`echo $cmdline | grep "image_dictionary=" -o`
		if [ ${#cmd_para} -gt 0 ]; then
			IMAGE_DICTIONARY=${cmdline#*image_dictionary=}
			IMAGE_DICTIONARY=${IMAGE_DICTIONARY%% *}
			IMAGE_DICTIONARY=${IMAGE_DICTIONARY#/*}
			IMAGE_DICTIONARY=${IMAGE_DICTIONARY%/*}
			IMAGE_DICTIONARY="${MNT_DIR%/*}/$DEST_PARTITION/$IMAGE_DICTIONARY"
		fi
		cmd_para=`echo $cmdline | grep "exit=" -o`
		if [ ${#cmd_para} -gt 0 ]; then
			EXIT_TYPE=${cmdline#*exit=}
			EXIT_TYPE=${EXIT_TYPE%% *}
			if  [ "$EXIT_TYPE" != "reboot" ] && [ "$EXIT_TYPE" != "halt" ] && [ "$EXIT_TYPE" != "poweroff" ]; then
				EXIT_TYPE=""
			fi
		fi
		if  [ "$DEST_PARTITION" = "" ] || [ "$IMAGE_DICTIONARY" = "" ]; then
			HANDLE_TYPE=""
		else
			if [ "$handle_type" = "restore" ]; then
				temp_part=$SOUR_PARTITION
				SOUR_PARTITION=$DEST_PARTITION
				DEST_PARTITION=$temp_part
			else
				if  [ "$SOUR_PARTITION" = "" ]; then
					HANDLE_TYPE=""
				fi
			fi
		fi
	fi
fi
}
#select operation type
select_operation_type()
{
if [ "$OPERATION_TYPE" = "Save" ];then 
	save=on
	restore=off
else 
	save=off restore=on
fi
  dialog $NO_SHADOW --backtitle $BACKTITLE --title "Operation type"  --no-cancel --radiolist "Press space key to select one item.  \nIf you would use some movable disk,please insert it and wait several seconds.\nTo exit this program ,please press ESC" $DIALOG_HEIGH $DIALOG_WIDTH $DIALOG_HEIGH "Save" "Save partition into a new image file" $save "Restore" "Restore partition from an image file" $restore "SaveTable" "Save partition table only[after 0.1.4,automatic save the table when save partition]" off "RestoreTable" "Restore the partition table to some disk. DANGEROUS!" off "MC" "Midnight Commander,a visual file manager" off "Exit" "Exit program. And can type \"minibackup\" to run this program again" off "Restart" "Exit system and restart computer." off  "Power Off" "Exit system and turn power off." off  2> /tmp/tempFile
 anser=$?
 OPERATION_TYPE=`cat /tmp/tempFile`
 return $anser
}

select_disk()
{
local temp_str="RestoreTable: Select the dest disk"
if [ "$OPERATION_TYPE" = "SaveTable" ]; then temp_str="SaveTable: Select the source disk"; fi
echo " dialog  $NO_SHADOW --backtitle $BACKTITLE --title \"$temp_str\"  --radiolist \"Press space key to select one item.   To exit this program ,please press ESC\" $DIALOG_HEIGH $DIALOG_WIDTH $DIALOG_HEIGH " | tr -d '\n'  > /tmp/miniD.sh
sfdisk -s | grep "^/dev" | while read disk_name disk_size
do
	echo " \"${disk_name%:}\" \"$disk_size blocks\" off " | tr -d '\n' >> /tmp/miniD.sh
done
echo " 2> /tmp/tempFile" | tr -d '\n' >> /tmp/miniD.sh

SOUR_DISK=""
anser=0
while [ "$SOUR_DISK" = "" ]  && [ $anser -eq 0 ] 
do
	. /tmp/miniD.sh
	anser=$?
	SOUR_DISK=`cat /tmp/tempFile | tr -d '\n'`
done
return $anser
}

#find all partitions and their size ,filesystem, label
find_partitions() 
{
rm /tmp/partition_info.data 2> /dev/null
fsarchiver probe simple 2>&1 | grep "^\[/dev/"| tr -s '[]' ' ' | sed 's/^ \/dev\///'  | sed 's/<unknown>/<>/' | awk '{print $1,$2,$3,$4,$5}' | while read part fstype label size mgb
do
	#\nPartclone: support fat(12/16/32),ext(2/3/4),ntfs,xfs,hfs,hfsplus\
	#\nPartimage: support fat(16/32),ext(2/3),ntfs,xfs,hfs,jfs,ufs,hpfs"\
	#support=`echo 'ext2 ext3 ext4 fat12 vfat fat16 fat32 ntfs reiserfs reiser4 xfs hfsplus ufs2' | grep $fstype -o`
	support=`echo 'ext2 ext3 ext4 vfat fat12 fat16 fat32 ntfs xfs hfsplus hfs jfs ufs' | grep $fstype -o`
	if [ ${#support} -eq 0 ]; then  support="["$NOT_SUPPORT_STR"]"; else support=""; fi
	echo $part" "$fstype" "$label" "$size$mgb""$support >> /tmp/partition_info.data
done
}

select_sour_partition()
{
local temp_str="Error: Null Type"
if [ "$OPERATION_TYPE" = "Save" ]; then
	temp_str="Select source partition"; 
elif [ "$OPERATION_TYPE" = "Restore" ]; then
	temp_str="Select the partition which contains the image file."
elif [ "$OPERATION_TYPE" = "SaveTable" ]; then
	temp_str="Select the partition where to save the partition table file."
elif [ "$OPERATION_TYPE" = "RestoreTable" ]; then
	temp_str="Select the partition which contains the partition table file."
fi
echo " dialog  $NO_SHADOW --backtitle $BACKTITLE --title \"$temp_str\"  --radiolist \"Press space key to select one item.   To exit this program ,please press ESC\" $DIALOG_HEIGH $DIALOG_WIDTH $DIALOG_HEIGH " | tr -d '\n'  > /tmp/miniD.sh
cat /tmp/partition_info.data | while read part system
do
	echo " \"$part\" \"$system \" off " | tr -d '\n' >> /tmp/miniD.sh
done
echo " 2> /tmp/tempFile" | tr -d '\n' >> /tmp/miniD.sh

SOUR_PARTITION=""
anser=0
while [ "$SOUR_PARTITION" = "" ]  && [ $anser -eq 0 ] 
do
	. /tmp/miniD.sh
	anser=$?
	SOUR_PARTITION=`cat /tmp/tempFile | tr -d '\n'`
	notSupport=`cat /tmp/partition_info.data | grep  "^$SOUR_PARTITION\>" | grep "$NOT_SUPPORT_STR"`
	if [ ${#notSupport} -gt 0 ]; then  SOUR_PARTITION=""; fi
done
return $anser
}

select_dest_partition()
{
local temp_str="Select the partition which will be restored from the image file."
if [ "$OPERATION_TYPE" = "Save" ]; then temp_str="Select destination partition where to store partition image."; fi
echo " dialog  $NO_SHADOW --backtitle $BACKTITLE --title \"$temp_str\"  --radiolist \"Press space key to select one item. To exit this program ,please press ESC\" $DIALOG_HEIGH $DIALOG_WIDTH $DIALOG_HEIGH " | tr -d '\n'  > /tmp/miniD.sh
cat /tmp/partition_info.data | grep  "^$SOUR_PARTITION\>" -v | while read part system
do
	echo " \"$part\" \"$system \" off " | tr -d '\n' >> /tmp/miniD.sh
done
echo " 2> /tmp/tempFile" | tr -d '\n' >> /tmp/miniD.sh

#if the partition table is same, then avoid the selection of target partition
if [ "$OPERATION_TYPE" = "Restore" ]; then 
	fdisk -l  > "/tmp/partition.info"
	local partition_table_diff=`diff "/tmp/partition.info" $IMAGE_DICTIONARY"/partition.info"`
	if [ ${#partition_table_diff} -eq 0 ];then
		DEST_PARTITION=`cat $IMAGE_DICTIONARY"/minibackup.info" | grep "^PARTITION\>" | awk '{print $2}'`
		if [ ${#DEST_PARTITION} -gt 0 ]; then return 0; fi
	fi
fi

DEST_PARTITION=""
anser=0
while [ "$DEST_PARTITION" = "" ]  && [ $anser -eq 0 ] 
do
	. /tmp/miniD.sh
	anser=$?
	DEST_PARTITION=`cat /tmp/tempFile | tr -d '\n'`
	notSupport=`cat /tmp/partition_info.data | grep  "^$DEST_PARTITION\>" | grep "$NOT_SUPPORT_STR"`
	if [ ${#notSupport} -gt 0 ]; then  DEST_PARTITION=""; fi
done
return $anser
}

select_dictionary()
{
local dic_name=""
local image_partition=$SOUR_PARTITION
if [ "$OPERATION_TYPE" = "Save" ]; then image_partition=$DEST_PARTITION; fi
umount $MNT_DIR$image_partition 2> /dev/null #must execute this code. perheps some movable disk insert... 
local fsType=`cat /tmp/partition_info.data | grep  "^$image_partition\>" | awk '{print $2}'`
local dia_heigh=`expr $DIALOG_HEIGH - 10`
mkdir $MNT_DIR$image_partition 2> /dev/null
fsck.$fsType "/dev/"$image_partition -p 2>> $LOG_FILE 1> /dev/null #Must fsck, or sometimes it will be mounted on read-only mode
if [ "$fsType" = "ntfs" ] ; then fsType="ntfs-3g"; fi
mount -t $fsType '/dev/'$image_partition $MNT_DIR$image_partition 2> /dev/null
IMAGE_DICTIONARY=`mount | grep -m 1 '/dev/'$image_partition | awk '{print $3}'` #perheps one partition mounted on multi points
anser=0
if [ "$OPERATION_TYPE" = "Save" ]; then
	while [ -d $IMAGE_DICTIONARY ] && [ $anser -eq 0 ] 
	do
		dialog  --backtitle $BACKTITLE" -- Use space-bar to copy selection into text-entry window. " --title "Select Image Dictionary"   --dselect "$IMAGE_DICTIONARY/"  $dia_heigh $DIALOG_WIDTH 2> /tmp/tempFile 
		anser=$?
		dic_name=`cat /tmp/tempFile`
		if [ -f $dic_name ]; then
			dialog  $NO_SHADOW --backtitle $BACKTITLE --title "Select Image Dictionary"  --msgbox "$dic_name is an existing file. Please input a new dictionary." $DIALOG_HEIGH $DIALOG_WIDTH 
			continue; 
		fi 
		IMAGE_DICTIONARY=${dic_name%/}
	done
elif [ "$OPERATION_TYPE" = "Restore" ]; then 
	while   [ ! -f $IMAGE_DICTIONARY"/partition.info"  ] && [ $anser -eq 0 ]
	do
		dialog  --backtitle $BACKTITLE" -- Use space-bar to copy selection into text-entry window. " --title "Select Image Dictionary"   --dselect "$IMAGE_DICTIONARY/"  $dia_heigh $DIALOG_WIDTH 2> /tmp/tempFile 
		anser=$?
		dic_name=`cat /tmp/tempFile`
		IMAGE_DICTIONARY=${dic_name%/}
	done
elif [ "$OPERATION_TYPE" = "SaveTable" ]; then
	while [ -f $dic_name ] && [ $anser -eq 0 ] 
	do
		dialog  --backtitle $BACKTITLE" -- Use space-bar to copy selection into text-entry window. " --title "Select Dictionary to save Partition Table File"   --dselect "$IMAGE_DICTIONARY/"  $dia_heigh $DIALOG_WIDTH 2> /tmp/tempFile 
		anser=$?
		dic_name=`cat /tmp/tempFile`
		if [ -f $dic_name ]; then
			dialog  $NO_SHADOW --backtitle $BACKTITLE --title "Select Dictionary to save Partition Table File"  --msgbox "$dic_name is an existing file. Please input a new dictionary or existing dictionary." $DIALOG_HEIGH $DIALOG_WIDTH 
			continue; 
		fi 
		IMAGE_DICTIONARY=${dic_name%/}
	done
elif [ "$OPERATION_TYPE" = "RestoreTable" ]; then 
	#first time, perhaps the file already exist in the root dictionary of the partition, but should let people to select
	dialog  --backtitle $BACKTITLE" -- Use space-bar to copy selection into text-entry window. " --title "Select Dictionary contian the Partition Table File"   --dselect "$IMAGE_DICTIONARY/"  $dia_heigh $DIALOG_WIDTH 2> /tmp/tempFile 
	anser=$?
	dic_name=`cat /tmp/tempFile`
	IMAGE_DICTIONARY=${dic_name%/}
	while [ ! -f $IMAGE_DICTIONARY"/partition_table.info" ] && [ $anser -eq 0 ]
	do
		dialog  --backtitle $BACKTITLE" -- Use space-bar to copy selection into text-entry window. " --title "Select Dictionary contian the Partition Table File"   --dselect "$IMAGE_DICTIONARY/"  $dia_heigh $DIALOG_WIDTH 2> /tmp/tempFile 
		anser=$?
		dic_name=`cat /tmp/tempFile`
		IMAGE_DICTIONARY=${dic_name%/}
	done
fi
return $anser
}

#select operation type
select_tool_program()
{
local fsType=`cat /tmp/partition_info.data | grep  "^$SOUR_PARTITION\>" | awk '{print $2}'`
local only_partimage_support=`echo 'hfs jfs ufs' | grep $fstype -o`
 
#cmd_str=$cmd_str"\"partimage-gzip\" \"Support ufs file system.\" off"
if [ ${#only_partimage_support} -gt 0 ]; then  TOOL_TYPE="partimage-gzip"; return 0; fi

local cpu_1=`cat /proc/cpuinfo  | grep "^processor\>" | grep "1" -o `
#if [ ${#cpu_1} -gt 0 ];then TOOL_TYPE="partclone-gzip";return 0; fi

#\nPartclone: support fat(12/16/32),ext(2/3/4),ntfs,xfs,hfs,hfsplus\
#\nPartimage: support fat(16/32),ext(2/3),ntfs,xfs,hfs,jfs,ufs,hpfs\" \
local cmd_str="dialog $NO_SHADOW --backtitle $BACKTITLE --title \"Select Tool\"  --no-cancel --radiolist \"Press space key to select one item.\nWith single-core CPU,lzo mode is more faster,but with multi-core CPU the speed is similar. \"  $DIALOG_HEIGH $DIALOG_WIDTH $DIALOG_HEIGH "
cmd_str=$cmd_str"\"partclone-lzo\" \"20%-100% faster,but 15%-20% larger,than gzip\" off "
cmd_str=$cmd_str"\"partclone-gzip\" \"High compress level,but normal speed.\" on "
cmd_str=$cmd_str" 2> /tmp/tempFile"
 #"partclone-lzma" "Very high compress level, but very low speed." off 
 #"fsarchiver-lzo" "" off 
 eval $cmd_str
 anser=$?
 TOOL_TYPE=`cat /tmp/tempFile`
 return $anser
}

run_mc()
{
find_partitions
local part=""
local fsType=""
local count=0
echo "mc " | tr -d '\n' > /tmp/tempFile
cat /tmp/partition_info.data | grep  "$NOT_SUPPORT_STR\>" -v | while read part fsType other_info
do
	#umount "/dev/"$part 2> /dev/null
	mkdir  $MNT_DIR$part 2> /dev/null
	if [ "$fsType" = "ntfs" ] ; then fsType="ntfs-3g"; fi
	mount -t $fsType '/dev/'$part $MNT_DIR$part 2> /dev/null
	count=`expr $count + 1 `
	if [ $count -lt 3 ] ; then echo "$MNT_DIR$part " | tr -d '\n' >> /tmp/tempFile; fi
done
eval ` cat /tmp/tempFile`
}

save_or_restore()
{
local per=0
local sour=`grep "^$SOUR_PARTITION\>" /tmp/partition_info.data`
local dest=`grep "^$DEST_PARTITION\>" /tmp/partition_info.data`
local fsType=""
local successful=0
local file_name=""
local image_partition=""
local image_partition_size=""
local dest_partition_size=""
local cmd_str=""
local info_str="Operation Type	: "$OPERATION_TYPE"\nDest Partition	:"$dest"\nImage Dictionary  :"$IMAGE_DICTIONARY"\n\n"
local info_str_for_success="Operation Type	: "$OPERATION_TYPE"\nDest Partition	: "$dest"\nImage Dictionary : "$IMAGE_DICTIONARY"\n\n"
if [ "$OPERATION_TYPE" = "Save" ]; then 
	info_str="Operation Type	: "$OPERATION_TYPE"\nSource Partition	: "$sour"\nDest Partition	: "$dest"\nImage Dictionary	: "$IMAGE_DICTIONARY"\nCompress Tool   : $TOOL_TYPE \n\n"; 
	info_str_for_success="Operation Type	: "$OPERATION_TYPE"\nSource Partition	:"$sour"\nImage Dictionary	:"$IMAGE_DICTIONARY"\nCompress Tool   : $TOOL_TYPE \n\n"
fi

dialog  $NO_SHADOW --backtitle $BACKTITLE --title "Confirm To "$OPERATION_TYPE  --yesno "$info_str\n\n  	Are you confirm?" $DIALOG_HEIGH $DIALOG_WIDTH   
if [ ! $? -eq 0 ];then return ; fi 

echo $per | dialog $NO_SHADOW --backtitle $BACKTITLE --title $OPERATION_TYPE --gauge "$info_str     Handling ..." $DIALOG_HEIGH $DIALOG_WIDTH   

if [ "$OPERATION_TYPE" = "Save" ]; then 
	umount "/dev/"$SOUR_PARTITION 1> /dev/null 2> /dev/null
	fsType=`cat /tmp/partition_info.data | grep  "^$SOUR_PARTITION\>" | awk '{print $2}'`
	fsck.$fsType "/dev/"$SOUR_PARTITION -p 2>> $LOG_FILE 1> /dev/null 
	mkdir $IMAGE_DICTIONARY 2>> $LOG_FILE 1> /dev/null
	echo "PARTITION $SOUR_PARTITION $fsType $TOOL_TYPE" > $IMAGE_DICTIONARY"/minibackup.info"
	fdisk -l  > $IMAGE_DICTIONARY"/partition.info"
	sfdisk -l -uS  "/dev/"$SOUR_PARTITION > $IMAGE_DICTIONARY"/partition_table.info"
	if [ "$TOOL_TYPE" = "partimage-gzip" ]; then
		cmd_str="partimage -z1 -o  --volume=650 -b -d save /dev/$SOUR_PARTITION $IMAGE_DICTIONARY/$SOUR_PARTITION.partimg.gz"
	elif [ "$TOOL_TYPE" = "partclone-gzip" ]; then
		file_name=$IMAGE_DICTIONARY"/"$SOUR_PARTITION".partclone.img.gz"
		#cmd_str="(partclone.$fsType -c -X -s /dev/$SOUR_PARTITION -O - 2>&3  | gzip -1 > $file_name )  3>&1 "
		#cmd_str="(partclone.$fsType -c -X -s /dev/$SOUR_PARTITION -O - 2>&3  | pigz -1 > $file_name )  3>&1 "
		cmd_str="(partclone.$fsType -c -X -s /dev/$SOUR_PARTITION -O - 2>&3  | pigz -1 -c | split -b 650m - $file_name. )  3>&1 "
	elif [ "$TOOL_TYPE" = "partclone-lzma" ]; then
		file_name=$IMAGE_DICTIONARY"/"$SOUR_PARTITION".partclone.img.lzma"
		cmd_str="(partclone.$fsType -c -X -s /dev/$SOUR_PARTITION -O - 2>&3  | lzma -1 > $file_name )  3>&1 "
	elif [ "$TOOL_TYPE" = "partclone-lzo" ]; then
		file_name=$IMAGE_DICTIONARY"/"$SOUR_PARTITION".partclone.img.lzo"
		#cmd_str="(partclone.$fsType -c -X -s /dev/$SOUR_PARTITION -O - 2>&3  | lzop > $file_name )  3>&1 "
		cmd_str="(partclone.$fsType -c -X -s /dev/$SOUR_PARTITION -O - 2>&3  | lzop -c | split -b 650m - $file_name. )  3>&1 "
	elif [ "$TOOL_TYPE" = "fsarchiver-lzo" ]; then
		file_name=$IMAGE_DICTIONARY"/"$SOUR_PARTITION".fsarchiver.fsa"
		cmd_str="time fsarchiver -j 2 -z1 savefs $file_name /dev/$SOUR_PARTITION "
	else #fsarchiver-lzma
		file_name=$IMAGE_DICTIONARY"/"$SOUR_PARTITION".fsarchiver.fsa"
		cmd_str="time fsarchiver -j 2 -z9 savefs $file_name /dev/$SOUR_PARTITION "
	fi

else
	umount "/dev/"$DEST_PARTITION 1> /dev/null 2> /dev/null
	fsType=`cat $IMAGE_DICTIONARY"/minibackup.info" | grep  "^PARTITION\>" | awk '{print $3}'`
	image_partition=`cat $IMAGE_DICTIONARY"/minibackup.info" | grep  "^PARTITION\>" | awk '{print $2}'`
	image_partition_size=`cat $IMAGE_DICTIONARY"/partition.info" | grep  "^/dev/$image_partition\>" | tr -d '*' | awk '{print $4}'`
	TOOL_TYPE=`cat $IMAGE_DICTIONARY"/minibackup.info" | grep  "^PARTITION\>" | awk '{print $4}'`
	dest_partition_size=`fdisk -l | grep  "^/dev/$DEST_PARTITION\>" | tr -d '*' | awk '{print $4}'`
	if [ $image_partition_size != $dest_partition_size ]; then
		dialog  $NO_SHADOW --backtitle $BACKTITLE --title $OPERATION_TYPE  --msgbox "The dest partition's size is not as same as the image! Restore opetion stop! " $DIALOG_HEIGH $DIALOG_WIDTH   
		return
	fi

	fsck.$fsType "/dev/"$DEST_PARTITION -p 1>> $LOG_FILE 2>> $LOG_FILE
	if [ "$TOOL_TYPE" = "partimage-gzip" ]; then
		cmd_str="partimage -b restore /dev/$DEST_PARTITION $IMAGE_DICTIONARY/$image_partition.partimg.gz.000"
	elif [ "$TOOL_TYPE" = "partclone-gzip" ]; then
		file_name=$IMAGE_DICTIONARY"/"$image_partition".partclone.img.gz"
		#cmd_str="( gunzip < $file_name | partclone.$fsType -r -X -s - -O /dev/$DEST_PARTITION 2>&3 ) 3>&1 "
		#cmd_str="( pigz -d -c $file_name | partclone.$fsType -r -X -s - -O /dev/$DEST_PARTITION 2>&3 ) 3>&1 "
		cmd_str="( cat $file_name.* | pigz -d -c | partclone.$fsType -r -X -s - -O /dev/$DEST_PARTITION 2>&3 ) 3>&1 "
	elif [ "$TOOL_TYPE" = "partclone-lzma" ]; then
		file_name=$IMAGE_DICTIONARY"/"$image_partition".partclone.img.lzma"
		cmd_str="( unlzma < $file_name | partclone.$fsType -r -X -s - -O /dev/$DEST_PARTITION 2>&3 ) 3>&1 "
	elif [ "$TOOL_TYPE" = "partclone-lzo" ]; then
		file_name=$IMAGE_DICTIONARY"/"$image_partition".partclone.img.lzo"
		#cmd_str="( lzop -dc < $file_name | partclone.$fsType -r -X -s - -O /dev/$DEST_PARTITION 2>&3 ) 3>&1 "
		cmd_str="( cat $file_name.* | lzop -dc | partclone.$fsType -r -X -s - -O /dev/$DEST_PARTITION 2>&3 ) 3>&1 "
	else
		file_name=$IMAGE_DICTIONARY"/"$image_partition".fsarchiver.fsa"
		cmd_str="time fsarchiver restfs $file_name id=0,dest=/dev/$DEST_PARTITION "
	fi
fi

if [ "$TOOL_TYPE" = "partimage-gzip" ]; then
	eval $cmd_str
	return
elif [ "$TOOL_TYPE" = "fsarchiver-lzo" ]; then
	eval $cmd_str
	return
fi

echo $cmd_str >> $LOG_FILE

				#temp=`echo $line | sed 's/, */\\n/g' `
				#temp=`echo $line | tr -s ',' '\n' `
if [ ! -d /var/log ]; then mkdir /var/log ; fi
rm /var/log/partclone.log 2> /dev/null
(eval $cmd_str) | dialog $NO_SHADOW --backtitle $BACKTITLE --title "$OPERATION_TYPE" --gauge "$info_str$line" $DIALOG_HEIGH $DIALOG_WIDTH 

if [ -e "/var/log/partclone.log" ] && [ `cat /var/log/partclone.log | grep "successful" -o ` = "successful" ]; then  
	info_str_for_success=$info_str_for_success`cat /var/log/partclone.log | grep '^Space in use:' | sed 's/^Space in use/ Data Size  /'`"\n"
	info_str_for_success=$info_str_for_success`cat /var/log/partclone.log | grep '^ Total Time :'`
	dialog  $NO_SHADOW --backtitle $BACKTITLE --title $OPERATION_TYPE  --msgbox "$info_str_for_success \n\n Operation successful !" $DIALOG_HEIGH $DIALOG_WIDTH  
else
	dialog  $NO_SHADOW --backtitle $BACKTITLE --title $OPERATION_TYPE  --msgbox "$info_str_for_success \n Operation failed !!\n " $DIALOG_HEIGH $DIALOG_WIDTH   
	dialog  $NO_SHADOW --backtitle $BACKTITLE --title "Log file:$LOG_FILE"  --tailbox $LOG_FILE $DIALOG_HEIGH $DIALOG_WIDTH   
fi

}

save_or_restore_table()
{
if [ "$OPERATION_TYPE" = "SaveTable" ]; then
	if [ ! -d $IMAGE_DICTIONARY ]; then mkdir $IMAGE_DICTIONARY; fi
	rm /tmp/save_table.log 2> /dev/null 
	sfdisk -l -uS  $SOUR_DISK 1> $IMAGE_DICTIONARY/partition_table.info 2> /tmp/save_table.log
	local err_info=`cat /tmp/save_table.log` 2> /dev/null
	if [ ${#err_info} -gt 0 ]; then  
		info_str_for_success="Some Error:\n"
		info_str_for_success=$info_str_for_success`cat /tmp/save_table.log`
		dialog  $NO_SHADOW --backtitle $BACKTITLE --title $OPERATION_TYPE  --msgbox "$info_str_for_success \n Operation failed !!\n\n " $DIALOG_HEIGH $DIALOG_WIDTH   
	else
		dialog  $NO_SHADOW --backtitle $BACKTITLE --title $OPERATION_TYPE  --msgbox "Operation successful !\n\nPartition Table information of $SOUR_DISK has saved in $IMAGE_DICTIONARY/partition_table.info \n\n" $DIALOG_HEIGH $DIALOG_WIDTH  
	fi
else
	clear
	rm /tmp/partition_table.tmp 2> /dev/null 
	cat $IMAGE_DICTIONARY/partition_table.info | grep "^/dev/" | tr -d '*' | while read p_name p_start p_end p_size p_id p_system
	do
		echo " $p_start $p_size $p_id  " >> /tmp/partition_table.tmp
	done

	rm /tmp/save_table.log 2> /dev/null 
	cat /tmp/partition_table.tmp | sfdisk $SOUR_DISK -uS | tee  /tmp/save_table.log 2>&1 | tee /tmp/save_table.log

	sleep 2
	local err_info=`cat /tmp/save_table.log | grep "^Successfully" -o ` 2> /dev/null
	if [ ${#err_info} -eq 0 ]; then  
		info_str_for_success="Some Error:\n"
		info_str_for_success=$info_str_for_success`cat /tmp/save_table.log`
		dialog  $NO_SHADOW --backtitle $BACKTITLE --title $OPERATION_TYPE  --msgbox "$info_str_for_success \n Operation failed !!\n\n " $DIALOG_HEIGH $DIALOG_WIDTH   
	else
		dialog  $NO_SHADOW --backtitle $BACKTITLE --title $OPERATION_TYPE  --msgbox "Operation successful !\n\nPartition Table information in $IMAGE_DICTIONARY/partition_table.info has restored to  $SOUR_DISK \n\n" $DIALOG_HEIGH $DIALOG_WIDTH  
	fi
fi
}

mount_partition_for_auto()
{
local image_partition=$SOUR_PARTITION
local fsType=`cat /tmp/partition_info.data | grep  "^$image_partition\>" | awk '{print $2}'`

if [ "$OPERATION_TYPE" = "Save" ]; then image_partition=$DEST_PARTITION; fi

mkdir $MNT_DIR$image_partition 2> /dev/null
umount $MNT_DIR$image_partition 2> /dev/null #must execute this code. perheps some movable disk insert... 
fsck.$fsType "/dev/"$image_partition -p 2>> $LOG_FILE 1> /dev/null #Must fsck, or sometimes it will be mounted on read-only mode
if [ "$fsType" = "ntfs" ] ; then fsType="ntfs-3g"; fi
mount -t $fsType '/dev/'$image_partition $MNT_DIR$image_partition 2> /dev/null

if [ "$OPERATION_TYPE" = "Restore" ] && [ "$DEST_PARTITION" = "" ]; then 
	fdisk -l  > "/tmp/partition.info"
	local partition_table_diff=`diff "/tmp/partition.info" $IMAGE_DICTIONARY"/partition.info"`
	if [ ${#partition_table_diff} -eq 0 ];then
		DEST_PARTITION=`cat $IMAGE_DICTIONARY"/minibackup.info" | grep "^PARTITION\>" | awk '{print $2}'`
	else
		HANDLE_TYPE=""
	fi
fi
}

main()
{

init_parameters

if [ "$HANDLE_TYPE" = "auto" ]; then
	find_partitions
	mount_partition_for_auto
	if [ "$HANDLE_TYPE" = "auto" ]; then
		save_or_restore
		if [ "$HANDLE_TYPE" = "auto" ]; then
			`$EXIT_TYPE`
		fi
	fi
fi

while true 
do
	select_operation_type 
	if [ $? -eq 255 ]; then return; fi
	case $OPERATION_TYPE  in 
		"MC") run_mc;continue;; 
		"Exit") return ;; 
		"Restart") reboot;return ;; 
		"Power Off") poweroff;return ;; 
	esac

	find_partitions

	select_sour_partition
	case $? in 1) continue ;; 255) return ;; esac
	# 0: enter ; 1:cancel ;  255: ESC

	if [ "$OPERATION_TYPE" = "Save" ] || [ "$OPERATION_TYPE" = "Restore" ]; then

		if [ "$OPERATION_TYPE" = "Save" ]; then
			select_dest_partition
			case $? in 1) continue ;; 255) return ;; esac

			select_dictionary
			case $? in 1) continue ;; 255) return ;; esac

			select_tool_program
			case $? in 1) continue ;; 255) return ;; esac
		else #Restore
			select_dictionary
			case $? in 1) continue ;; 255) return ;; esac

			select_dest_partition
			case $? in 1) continue ;; 255) return ;; esac
		fi
		save_or_restore
	else
		select_dictionary
		case $? in 1) continue ;; 255) return ;; esac
		
		select_disk
		case $? in 1) continue ;; 255) return ;; esac

		save_or_restore_table
	fi
done
}
main
